package com.github.cosycode.imgtool.action;

import com.github.cosycode.common.ext.bean.DoubleBean;
import com.github.cosycode.common.ext.hub.Throws;
import com.github.cosycode.common.lang.BaseRuntimeException;
import com.github.cosycode.common.util.io.FileSystemUtils;
import com.github.cosycode.common.util.otr.PrintTool;
import com.github.cosycode.flow.base.AbstractAction;
import com.github.cosycode.imgtool.ctrl.MarkdownFileProcessor;
import com.github.cosycode.imgtool.rule.CheckConfig;
import com.github.cosycode.imgtool.rule.MarkdownRepairSource;
import com.github.cosycode.imgtool.tool.ImageCheckTool;
import com.github.cosycode.imgtool.util.FileUtils;
import lombok.AllArgsConstructor;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * <b>Description : </b>
 * <p>
 * <b>created in </b> 2022/12/15
 * </p>
 *
 * @author pengfchen
 * @since 1.0
 **/
@AllArgsConstructor
public class CleanDangingPictureAction extends AbstractAction<String> {

    /**
     * 扫描的文件路径
     */
    private final String scanFilePath;

    /**
     * 存放待删除的文件路径
     */
    private final String deletePathDir;
    /**
     * 存放待删除的文件路径
     */
    private final CheckConfig config;

    public static void main(String[] args) throws Exception {
        String path = "D:\\Users\\Desktop\\working-note";
        String pathDir = path + ".delete";
        CheckConfig config = new CheckConfig();

//        config.setWebPathEnable(true, false);
        config.setRelatePathEnable(true);
        config.setAbsolutePathEnable(true);
        config.setRootPathEnable(path);

        boolean dryRun = true;

        CleanDangingPictureAction cleanDangingPictureAction = new CleanDangingPictureAction(path, pathDir, config);
        cleanDangingPictureAction.setDryRun(dryRun);
        cleanDangingPictureAction.doProcess();
    }

    /**
     * 扫描出 danging 的图片(没有 markdown 文件引用的图片)
     *
     * @param scanMdFilePath  扫描的 markdown 文件路径
     * @param scanPicFilePath 扫描的 pic 文件路径
     * @return 扫描出的 dangling 图片
     * @throws IOException 对 markdown 文件进行扫描的时候 对 markdown 文件的读取异常
     */
    public static List<File> scanDanglingPic(String scanMdFilePath, String scanPicFilePath, CheckConfig config) throws IOException {
        // 1. 数据源
        MarkdownRepairSource source = new MarkdownRepairSource();
        source.addMarkdownFile(new File(scanMdFilePath));

        /* 3. 扫描所有的 markdown 文件, 将匹配到图片的 link 放到 mdFileImgUrlSet 里面, 将未匹配到图片的 link 放到 notFoundImgUrl$douList 中 */
        Set<String> mdFileImgUrlSet = new HashSet<>();
        // 用于存放 md 文件内失效 img 链接, 且通过文件名没有找到对应图片的链接
        List<DoubleBean<String, String>> notFoundImgUrl$douList = new ArrayList<>();
        for (String mdFilePath : source.getMarkdownFileSet()) {
            File file = new File(mdFilePath);
            MarkdownFileProcessor.findMdImgLink(file, config, rst -> {
                boolean exist = rst.isExist();
                if (exist) {
                    mdFileImgUrlSet.add(rst.getRealImgPath());
                } else {
                    notFoundImgUrl$douList.add(DoubleBean.of(mdFilePath, rst.getRealImgPath()));
                }
            });
        }

        /* 4. 在此加一个验证, 只有所有的 markdown 文件中的 link 均可以正常找到对应的图片, 才可以出发后续的删除*/
        if (!notFoundImgUrl$douList.isEmpty()) {
            notFoundImgUrl$douList.forEach(b -> {
                PrintTool.warn("[未匹配到 picture] {} ==> {}", b.getO1(), b.getO2());
            });
            throw new BaseRuntimeException("发现未匹配到图片的 link, 删除的时候最好保证, 所有 markdown 文件中的 link 对应的图片均存在");
        }

        /* 5. 遍历存放图片的文件夹, 如果图片不在 mdFileImgUrlSet 里面, 则表示图片没有被 markdown 文件引用, 表示是 dangling 图片. */
        return FileSystemUtils.findFileFromDir(new File(scanPicFilePath), f -> {
            boolean isImage = ImageCheckTool.isImage(f);
            if (!isImage) {
                return false;
            }
            String canonicalPath = Throws.runtimeEpt(f::getCanonicalPath);
            return !mdFileImgUrlSet.contains(canonicalPath);
        }, true);
    }

    @Override
    public String doProcess() throws Exception {
        List<File> dangingPicList = scanDanglingPic(scanFilePath, scanFilePath, config);

        /* 6. 执行文件删除 */
        for (File file : dangingPicList) {
            record.appendRecord("[dangling pic] " + file.getPath());
            if (!dryRun) {
                FileUtils.moveFileToDir(file, new File(deletePathDir), dryRun);
            }
        }
        return "SUCCESS";
    }

}
